#include "mcu_init.h"
#include "tos_k.h"
#include "mqttclient.h"
#include "cJSON.h"
#include "sal_module_wrapper.h"
#include "mqtt_config.h"
#include "E53_SC2.h"
#include "esp8266.h"

#define ESP8266_SSID "TEST"
#define ESP8266_PWD  "0987654321"

static hal_uart_port_t esp8266_port = HAL_UART_PORT_0;

k_event_t report_result_event;
k_event_flag_t report_success = 1 << 0;
k_event_flag_t report_fail = 1 << 1;


/***************************************************************
* 函数名称: tos_topic_handler
* 说    明: IoT Explorer下行数据处理
***************************************************************/
static void tos_topic_handler(void* client, message_data_t* msg)
{
    cJSON *root;
    cJSON *method;
    cJSON* cjson_status = NULL;
    char* status = NULL;
    k_event_flag_t event_flag = report_fail;

    /* 打印日志 */
    MQTT_LOG_I("-----------------------------------------------------------------------------------");
    MQTT_LOG_I("%s:%d %s()...\ntopic: %s, qos: %d. \nmessage:\n\t%s\n", __FILE__, __LINE__, __FUNCTION__,
            msg->topic_name, msg->message->qos, (char*)msg->message->payload);
    MQTT_LOG_I("-----------------------------------------------------------------------------------\n");

    // 1. 解析从云端收到的控制信息，示例控制信息为
    //"{"method":"control","clientToken":"clientToken-Xx-N_enad","params":{"power_switch":0}}"
    root = cJSON_Parse((char*)msg->message->payload);
    if (root == NULL) {
        printf("report reply message parser fail\r\n");
        cJSON_Delete(root);
        return;
    }

    // 2. 解析出method
    method = cJSON_GetObjectItem(root, "method");
    if (!method) {
        printf("Invalid json method\r\n");
        cJSON_Delete(root);
        return;
    }

    // 3. 解析出数据上报后平台回复的上报状态
    cjson_status = cJSON_GetObjectItem(root, "status");
    if (cjson_status) {
        // 4. 获取上报状态，判断上报成功或失败
        status = cJSON_GetStringValue(cjson_status);
        if (status == NULL) {
            printf("report reply status parser fail\r\n");
            event_flag = report_fail;
        } else {
            if (strstr(status, "success")) {
                event_flag = report_success;
            } else {
                event_flag = report_fail;
            }
        }
        cJSON_Delete(root);
        root = NULL;
        status = NULL;
        // 5. 触发事件
        tos_event_post(&report_result_event, event_flag);
        return;
    }
}

#define REPORT_SENSOR_DATA_TEMPLATE "{\"method\":\"report\",\"clientToken\":\"00000001\",\"params\":{\"Temperature\":%d,\"Accel_x\":%d,\"Accel_y\":%d,\"Accel_z\":%d,\"Cover_Status\":%d}}"
#define CONTROL_REPLY_DATA_TEMPLATE "{\"method\":\"control_reply\",\"clientToken\":\"%s\",\"code\":0,\"status\":\"ok\"}"

char report_buf[200];

/***************************************************************
* 函数名称: mqttclient_task
* 说    明: 主任务，连接平台以及发送上行数据
***************************************************************/
void mqttclient_task(void)
{
    int error;

    mqtt_client_t *client = NULL;

    mqtt_message_t msg;

    k_event_flag_t match_flag;

    E53_SC2_Data data;

    int X = 0, Y = 0, Z = 0;
    char display_temp[20] = { 0 };
    char display_accel_x[20] = { 0 };
    char display_accel_y[20] = { 0 };
    char display_accel_z[20] = { 0 };
    char coverStatus = 0;

    char  host_ip[20];

    memset(&msg, 0, sizeof(msg));

    esp8266_sal_init(esp8266_port);
    esp8266_join_ap(ESP8266_SSID, ESP8266_PWD);

    mqtt_log_init();

    client = mqtt_lease();

    tos_event_create(&report_result_event, (k_event_flag_t)0u);

    /* Domain Format: <your product ID>.iotcloud.tencentdevices.com */
    tos_sal_module_parse_domain(MQTT_SERVER_DOMAIN, host_ip, sizeof(host_ip));
    /*
        These infomation is generated by mqtt_config_gen.py tool in "TencentOS-tiny\tools" directory.
    */
    mqtt_set_port(client, MQTT_SERVER_PORT);
    mqtt_set_host(client, host_ip);
    mqtt_set_client_id(client, MQTT_CLIENT_ID);
    mqtt_set_user_name(client, MQTT_USR_NAME);
    mqtt_set_password(client, MQTT_PASSWORD);
    mqtt_set_clean_session(client, 1);

    error = mqtt_connect(client);

    MQTT_LOG_D("mqtt connect error is %#0x", error);

    error = mqtt_subscribe(client, MQTT_SUBSCRIBE_TOPIC_DOWN, QOS0, tos_topic_handler);

    MQTT_LOG_D("mqtt subscribe error is %#0x", error);

    while (1) {

        /* 读取传感器数据 */
        E53_SC2_Read_Data(&data);
        /* 显示传感器数据 */
        sprintf(display_temp, "TEMP:%d     ", (int)data.Temperature);
        LCD_ShowCharStr(5, 100, display_temp, WHITE, BLUE, 24);

        sprintf(display_accel_x, "ACCEL_X:%d    ", (int)data.Accel[ACCEL_X_AXIS]);
        LCD_ShowCharStr(5, 130, display_accel_x, WHITE, BLUE, 24);

        sprintf(display_accel_y, "ACCEL_Y:%d    ", (int)data.Accel[ACCEL_Y_AXIS]);
        LCD_ShowCharStr(5, 160, display_accel_y, WHITE, BLUE, 24);

        sprintf(display_accel_z, "ACCEL_Z:%d    ", (int)data.Accel[ACCEL_Z_AXIS]);
        LCD_ShowCharStr(5, 190, display_accel_z, WHITE, BLUE, 24);
        
        if (X == 0 && Y == 0 && Z == 0) {
            X = (int)data.Accel[ACCEL_X_AXIS];
            Y = (int)data.Accel[ACCEL_Y_AXIS];
            Z = (int)data.Accel[ACCEL_Z_AXIS];
        } else {
            if (X + 100 < data.Accel[ACCEL_X_AXIS] || X - 100 > data.Accel[ACCEL_X_AXIS] ||
                Y + 100 < data.Accel[ACCEL_Y_AXIS] || Y - 100 > data.Accel[ACCEL_Y_AXIS] ||
                Z + 100 < data.Accel[ACCEL_Z_AXIS] || Z - 100 > data.Accel[ACCEL_Z_AXIS]) {
                E53_SC2_LedD1_Set(OFF);
                E53_SC2_LedD2_Set(ON);
                coverStatus = 1;
            } else {
                E53_SC2_LedD1_Set(ON);
                E53_SC2_LedD2_Set(OFF);
                coverStatus = 0;
            }
        }
        /* 上报传感器数据 */
        memset(&msg, 0, sizeof(msg));
        memset(report_buf, 0, sizeof(report_buf));
        snprintf(report_buf, sizeof(report_buf), REPORT_SENSOR_DATA_TEMPLATE, (int)data.Temperature,
                (int)data.Accel[ACCEL_X_AXIS], (int)data.Accel[ACCEL_Y_AXIS], (int)data.Accel[ACCEL_Z_AXIS], coverStatus);
        msg.qos = QOS0;
        msg.payload = (void *)report_buf;
        error = mqtt_publish(client, MQTT_PUBLISH_TOPIC_UP, &msg);
        MQTT_LOG_D("mqtt publish error is %#0x", error);
        tos_event_pend(&report_result_event,
                       report_success | report_fail,
                       &match_flag,
                       TOS_TIME_FOREVER,
                       TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_CLR);

        if (match_flag == report_success) {
            printf("report to Tencent IoT Explorer success\r\n");

        } else if (match_flag == report_fail) {
            printf("report to Tencent IoT Explorer fail\r\n");
        }
        /* END*/
        
        tos_task_delay(5000);
    }
}

/***************************************************************
* 函数名称: application_entry
* 说    明: 应用入口
***************************************************************/
void application_entry(void *arg)
{
    E53_SC2_Init();
    mqttclient_task();
    while (1) {
        printf("This is a mqtt demo!\r\n");
        tos_task_delay(1000);
    }
}
